package com.example.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class ReflectionUtils {

    /**
     * 获取类上的注解
     * @param clazz 类
     * @param annotationClass 注解类型
     * @return 注解对象，如果不存在返回null
     */
    public static <A extends Annotation> A getClassAnnotation(Class<?> clazz, Class<A> annotationClass) {
        if (clazz == null || annotationClass == null) {
            return null;
        }
        return clazz.getAnnotation(annotationClass);
    }

    /**
     * 获取所有带有指定注解的字段列表
     */
    public static List<Field> getFieldsWithAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        List<Field> annotatedFields = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            if (field.isAnnotationPresent(annotationClass)) {
                annotatedFields.add(field);
            }
        }
        return annotatedFields;
    }

    /**
     * 判断类是否有指定注解
     * @param clazz 要检查的类
     * @param annotationClass 注解类型
     * @return 如果类有该注解返回true，否则返回false
     */
    public static boolean hasClassAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        if (clazz == null || annotationClass == null) {
            return false;
        }
        return clazz.isAnnotationPresent(annotationClass);
    }

    /**
     * 判断对象是否拥有所有指定字段
     * @param obj 要检查的对象
     * @param fieldNames 字段名数组
     * @return 如果对象拥有所有字段返回true，否则返回false
     */
    public static boolean hasAllFields(Object obj, String... fieldNames) {
        if (obj == null || fieldNames == null || fieldNames.length == 0) {
            return false;
        }

        for (String fieldName : fieldNames) {
            if (!hasField(obj, fieldName)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断对象是否拥有指定字段
     * @param obj 要检查的对象
     * @param fieldName 字段名
     * @return 如果对象拥有该字段返回true，否则返回false
     */
    public static boolean hasField(Object obj, String fieldName) {
        if (obj == null || fieldName == null || fieldName.trim().isEmpty()) {
            return false;
        }

        Class<?> clazz = obj.getClass();

        // 检查当前类及其所有父类（不包括Object类）
        while (clazz != null && clazz != Object.class) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                return true;
            } catch (NoSuchFieldException e) {
                // 当前类没有该字段，继续检查父类
                clazz = clazz.getSuperclass();
            }
        }

        return false;
    }

    /**
     * 给对象的指定字段设置值
     * @param obj 要设置值的对象
     * @param fieldName 字段名
     * @param value 要设置的值
     * @return 设置成功返回true，失败返回false
     */
    public static boolean setFieldValue(Object obj, String fieldName, Object value) {
        if (obj == null || fieldName == null || fieldName.trim().isEmpty()) {
            return false;
        }

        Class<?> clazz = obj.getClass();

        // 在当前类及其所有父类中查找字段
        while (clazz != null && clazz != Object.class) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true); // 设置可访问，即使是private字段

                // 类型转换处理
                Object convertedValue = convertValue(field.getType(), value);
                field.set(obj, convertedValue);
                return true;

            } catch (NoSuchFieldException e) {
                // 当前类没有该字段，继续检查父类
                clazz = clazz.getSuperclass();
            } catch (IllegalAccessException e) {
                System.err.println("无法访问字段: " + fieldName + ", 错误: " + e.getMessage());
                return false;
            } catch (IllegalArgumentException e) {
                System.err.println("字段类型不匹配: " + fieldName + ", 错误: " + e.getMessage());
                return false;
            }
        }

        System.err.println("未找到字段: " + fieldName);
        return false;
    }

    /**
     * 值类型转换
     * @param targetType 目标类型
     * @param value 原始值
     * @return 转换后的值
     */
    private static Object convertValue(Class<?> targetType, Object value) {
        if (value == null) {
            return null;
        }

        // 如果类型匹配，直接返回
        if (targetType.isInstance(value)) {
            return value;
        }

        // 基本类型和包装类型的处理
        try {
            if (targetType == int.class || targetType == Integer.class) {
                if (value instanceof Number) {
                    return ((Number) value).intValue();
                } else {
                    return Integer.parseInt(value.toString());
                }
            } else if (targetType == long.class || targetType == Long.class) {
                if (value instanceof Number) {
                    return ((Number) value).longValue();
                } else {
                    return Long.parseLong(value.toString());
                }
            } else if (targetType == double.class || targetType == Double.class) {
                if (value instanceof Number) {
                    return ((Number) value).doubleValue();
                } else {
                    return Double.parseDouble(value.toString());
                }
            } else if (targetType == float.class || targetType == Float.class) {
                if (value instanceof Number) {
                    return ((Number) value).floatValue();
                } else {
                    return Float.parseFloat(value.toString());
                }
            } else if (targetType == boolean.class || targetType == Boolean.class) {
                if (value instanceof Boolean) {
                    return value;
                } else {
                    return Boolean.parseBoolean(value.toString());
                }
            } else if (targetType == String.class) {
                return value.toString();
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无法将值 '" + value + "' 转换为类型: " + targetType.getName());
        }

        // 如果无法转换，抛出异常
        throw new IllegalArgumentException("不支持的类型转换: " + value.getClass().getName() + " -> " + targetType.getName());
    }

    /**
     * 获取字段的值
     * @param obj 对象
     * @param fieldName 字段名
     * @return 字段值，如果获取失败返回null
     */
    public static Object getFieldValue(Object obj, String fieldName) {
        if (obj == null || fieldName == null || fieldName.trim().isEmpty()) {
            return null;
        }

        Class<?> clazz = obj.getClass();

        while (clazz != null && clazz != Object.class) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            } catch (IllegalAccessException e) {
                System.err.println("无法访问字段: " + fieldName + ", 错误: " + e.getMessage());
                return null;
            }
        }

        return null;
    }
}
